package vn.com.lib.helper;

import java.util.List;

import org.springframework.jdbc.core.RowMapper;

import vn.com.lib.dao.BaseDao;
import vn.com.lib.model.PagingInfo;
import vn.com.lib.model.SearchResult;

public abstract class DaoHelper<E> extends BaseDao {

	private final Integer OFFSET = 10;
	private final Integer PAGE_INDEX = 1;
	private int totalItems;
	private SearchResult<E> searchResult;

	public DaoHelper() {
		this.searchResult = new SearchResult<E>();
	}

	/**
	 * Return id of record has been inserted
	 * 
	 * @param sql
	 * @param parameters
	 * @return
	 */
	public int insert(String sql, Object[] parameters) {
		getJdbcTemplate().update(sql, parameters);
		return getJdbcTemplate().queryForObject("SELECT last_insert_id()", Integer.class);
	}

	public void delete(String sql, Object[] parameters) {
		getJdbcTemplate().update(sql, parameters);
	}

	/**
	 * Query select with paging
	 * 
	 * @param sql
	 * @param rowMapper
	 * @param pagingInfo
	 * @return
	 */
	public SearchResult<E> queryPaging(String sql, Object[] parameters, RowMapper<Object> rowMapper, PagingInfo pagingInfo) {
		if (pagingInfo == null) {
			pagingInfo = initDefaultPaging();
		}
		getTotalRecords(sql, parameters);
		searchResult.setPagingInfo(pagingInfo);
		searchResult.getPagingInfo().setTotalItems(totalItems);
		searchResult.setSearchResult(getListResult(sql, parameters, rowMapper, computePageIndex(pagingInfo), pagingInfo.getOffset()));
		return searchResult;
	}

	@SuppressWarnings("unchecked")
	public SearchResult<E> query(String sql, Object[] parameters, RowMapper<Object> rowMapper) {
		if (parameters != null) {
			searchResult.setSearchResult((List<E>) getJdbcTemplate().query(sql, parameters, rowMapper));
		} else {
			searchResult.setSearchResult((List<E>) getJdbcTemplate().query(sql, rowMapper));
		}
		return searchResult;
	}

	@SuppressWarnings("unchecked")
	public List<E> getListResult(String sql, Object[] parameters, RowMapper<Object> rowMapper, int pageIndex, int offset) {
		StringBuilder sqlPaging = new StringBuilder();
		sqlPaging.append("SELECT * FROM (").append(sql).append(") AS A LIMIT ");
		sqlPaging.append(pageIndex).append(", ").append(offset);
		if (parameters == null) {
			return (List<E>) getJdbcTemplate().query(sqlPaging.toString(), rowMapper);
		}
		return ((List<E>) getJdbcTemplate().query(sqlPaging.toString(), parameters, rowMapper));
	}

	public void getTotalRecords(String sql, Object[] parameters) {
		StringBuilder countItemSql = new StringBuilder();
		countItemSql.append("SELECT count(A.id) FROM (").append(sql).append(") as A");
		if (parameters != null) {
			this.setTotalItems(getJdbcTemplate().queryForObject(countItemSql.toString(), parameters, Integer.class));
		} else {
			this.setTotalItems(getJdbcTemplate().queryForObject(countItemSql.toString(), Integer.class));
		}
	}

	public int computePageIndex(PagingInfo pagingInfo) {
		return ((pagingInfo.getPageIndex() - 1) * pagingInfo.getOffset());
	}

	public PagingInfo initDefaultPaging() {
		return new PagingInfo(OFFSET, PAGE_INDEX);
	}

	public int getTotalItems() {
		return totalItems;
	}

	public void setTotalItems(int totalItems) {
		this.totalItems = totalItems;
	}

}
